package com.far.permissions.support;

import com.far.permisions.rule.base.RuleResultInvoker;
import com.far.permissions.bean.RuleResult;
import com.far.permissions.tools.SqlParserTools;
import lombok.Data;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Data
public abstract class BaseSqlActuator {
    protected String originalSql;
    protected Map<String, String> tablesWithAlias;
    protected List<RuleResult> tablesRuleResult;
    protected String newSql;
    protected List<ParameterMapping> parameterMappings;
    protected RuleResultInvoker ruleResultInvoker;
    private boolean initialized = false;

    public BaseSqlActuator(BoundSql boundSql, RuleResultInvoker ruleResultInvoker) {
        this.originalSql = boundSql.getSql();
        this.newSql = boundSql.getSql();
        this.parameterMappings = boundSql.getParameterMappings();
        this.ruleResultInvoker = ruleResultInvoker;
    }

    protected abstract void doExecute() throws Exception;

    public BaseSqlActuator execute() throws Exception {
        if (!initialized){
            throw new RuntimeException("SqlActuator not init");
        }
        doExecute();
        return this;
    }

    protected List<ParameterMapping> removeParameterMappings(List<ParameterMapping> parameterMappings, List<RuleResult> tablesRuleResult) {
        Set<String> removeColumns = tablesRuleResult.stream().map(RuleResult::getColumn).collect(Collectors.toSet());
        return parameterMappings.stream()
                .filter((parameterMapping -> !removeColumns.contains(parameterMapping.getProperty())))
                .collect(Collectors.toList());
    }

    public void init() throws Exception {
        tablesWithAlias = SqlParserTools.getTablesWithAlias(originalSql);
        tablesRuleResult = ruleResultInvoker.getTablesRuleResult(tablesWithAlias.keySet());
        initialized = true;
    }
}
